from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from django import http

from apps.verifications.libs.captcha.captcha.captcha import captcha
from . import constants
from meiduo_mall.utils.response_code import RETCODE
import random
from apps.verifications.libs.yuntongxun.ccp_sms import sendTemplateSMS
import logging
from celery_tasks.sms.tasks import ccp_send_sms_code
# Create your views here.

# 创建日志输出器
logger = logging.getLogger("django")

##########短信验证码#################
class SMSCodeView(View):
    ''' 短信验证码'''
    def get(self,request,mobile):

        # 提取并判断发送短信验证码的标记是否存在,如果存在表示短信验证码60秒没到,则过于频繁
        redis_conn = get_redis_connection("verify_code")
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        if send_flag:
            return http.JsonResponse({"code":RETCODE.THROTTLINGERR,"errmsg":"发送短信过于频繁"})

        # 接受参数
        image_code_client = request.GET.get("image_code") # str
        uuid = request.GET.get("uuid")

        # 校验参数
        if not all([image_code_client,uuid]):
            return http.HttpResponseForbidden("缺少必传参数")

        # 提取图形验证码
        redis_conn = get_redis_connection("verify_code")
        image_code_server = redis_conn.get("img_%s" % uuid) # bytes
        if not image_code_server:
            return http.JsonResponse({"code":RETCODE.IMAGECODEERR,"errmsg":"图形验证码失效"})

        # 删除图形验证码:为了避免恶意用户恶意测试图形验证码,提取到了之后,将redis数据库中的删除
        redis_conn.delete("img_%s" % uuid)

        # 对比图形验证码:如果用户输入的验证码和服务器的不一样,就响应错误信息
        # 将bytes类型的image_code_server转成str类型(在python3中,从redis中提取出来的所有数据都是bytes类型的)
        image_code_server = image_code_server.decode()
        if image_code_client.lower() != image_code_server.lower():# 统一转成小写在比较
            return http.JsonResponse({"code":RETCODE.IMAGECODEERR,"errmsg":"图形验证码有误"})

        # 生成短信验证码: 随机6位数
        # random.randint(100000,999999) # 取值范围小,取不到100000以下的数
        sms_code = "%06d" % random.randint(0,999999)
        logger.info(sms_code)

        # 保存短信验证码
        # redis_conn.setex("key","有效期","value")
        # redis_conn.setex("sms_%s" % mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
        # 保存发送短信验证码的标记
        # redis_conn.setex("send_flag_%s" % mobile,constants.SEND_SMS_CODE_INTERVAL,"flag")

        # 创建Redis管道
        # 把多个命令打包到一起.这样就降低了阻塞概率.两个命令用一个请求来完成
        pl = redis_conn.pipeline()
        # 将Redis请求添加到管道
        pl.setex("sms_%s" % mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
        pl.setex("send_flag_%s" % mobile,constants.SEND_SMS_CODE_INTERVAL,"flag")
        # 执行求情  execute执行.  切记一定要执行execute()这个方法
        pl.execute()

        # 发送短信验证码  两个斜线 // 表示整除   5分钟.
        # 这是一个网络操作,非常耗时
        # sendTemplateSMS(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES // 60],constants.SEND_SMS_TEMPLATE_ID)
        # 异步发短信的任务
        # ccp_send_sms_code()  如此调用表示立即执行
        ccp_send_sms_code.delay(mobile,sms_code) # 延迟执行,不要立即执行,可以先执行后面的代码


        # 响应结果
        return http.JsonResponse({"code":RETCODE.OK,"errmsg":"发送短信验证码成功"})


##########图形验证码#################
class ImageCodeView(View):
    '''图形验证码'''

    def get(self,request,uuid): # 根据路由传入uuid参数
        '''提供图形验证码
        uuid 前端传入的用于唯一标识图形验证码属于哪个用户
        :return image/jpg
        '''
        # 接收参数  uuid已经接受完了参数
        # 校验参数  路由的正则就算校验了参数
        # 生成图形验证码(text,image)
        text, image = captcha.generate_captcha()
        # 保存图形验证码(text-->redis:2)
        # 创建连接到redis2号库的对象
        redis_conn = get_redis_connection("verify_code")
        # 使用redis操作redis2号库
        # redis_conn.set(uuid,text) # 图形验证码需要有效期,所以不使用set
        # redis_conn.setex("key","过期时间","value")
        redis_conn.setex("img_%s" % uuid,constants.IMAGE_CODE_REDIS_EXPIRES,text)

        # 响应图形验证码(image)
        return http.HttpResponse(image,content_type="image/jpg")





'''
# 异步发送短信验证码(但是性能较差)
import threading  # 新开子线程执行发送短信验证码

# 先发送短信验证码,再响应结果, main thread(默认在主线程)
# 加了子线程之后,子线程发送短信验证码
# 主线程: 响应结果
# 以上方案是使用了子线程将发送短信验证码的逻辑从主线程中解耦出来了,
'''